/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：太平金科-通用能力封装层-公共组件
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taipingframework.utility.extend;

import cn.hutool.json.JSONUtil;
import com.taipingframework.utility.exception.UtilityException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.MultiValueMap;

import java.net.InetSocketAddress;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.stream.Collectors;

public class AspectHelper {

    /**
     * 在切面中拼接Http请求入参字符串
     */
    public static StringJoiner requestParamJoiner(String packagePathName, String methodName, Object[] args) throws UtilityException {
        StringJoiner joiner = new StringJoiner(", ");
        HttpServletRequest request = ServletHelper.getRequest();
        // 获取请求头参数列表
        Map<String, Object> headerParamMap = new HashMap<>();
        Enumeration<String> headerNamesIter = request.getHeaderNames();
        while (headerNamesIter.hasMoreElements()) {
            String headerName = headerNamesIter.nextElement();
            String headerText = request.getHeader(headerName);
            headerParamMap.put(headerName, headerText);
        }

        // 获取URL参数列表
        Map<String, Object> urlParamMap = new HashMap<>();
        Enumeration<String> urlParamNamesIter = request.getParameterNames();
        while (urlParamNamesIter.hasMoreElements()) {
            String fieldName = urlParamNamesIter.nextElement();
            String[] fieldValueArray = request.getParameterValues(fieldName);
            String fieldValueStr = String.join(", ", fieldValueArray);
            if (fieldValueArray.length > 1) {
                fieldValueStr = StringUtils.join("[", fieldValueStr, "]");
            }
            urlParamMap.put(fieldName, fieldValueStr); // 说明，如果URL参数中某个key的value是数组，这里可能将无法还原出原始的url，如有需要，这部分编码仍要重构
        }
        StringBuffer requestUrl = request.getRequestURL();
        String urlParamStr = "";
        if (urlParamMap.size() > 0) {
            urlParamStr = "?" + urlParamMap.entrySet()
                    .stream()
                    .map((entry) -> StringUtils.join(entry.getKey(), "=", entry.getValue()))
                    .collect(Collectors.joining("&"));
            requestUrl.append(urlParamStr);
        }

        joiner.add(StringUtils.join("请求request_url=", requestUrl, " "));
        joiner.add(StringUtils.join("request_method=", request.getMethod()));
        joiner.add(StringUtils.join("char-encoding=", request.getCharacterEncoding()));
        joiner.add(StringUtils.join("请求remote_ip=", request.getRemoteAddr()));
        joiner.add(StringUtils.join("请求头 request_headers=", headerParamMap));
        joiner.add(StringUtils.join("地址入参 url_param=", urlParamStr));
        joiner.add(StringUtils.join("class_method=", packagePathName, ".", methodName));
        joiner.add(StringUtils.join("方法入参 method_args=", JSONUtil.toJsonStr(args)));
        return joiner;
    }

    /**
     * 在切面中拼接Http请求入参字符串
     */
    public static StringJoiner requestParamJoiner(ServerHttpRequest request, String packagePathName, String methodName, Object[] args) {
        StringJoiner joiner = new StringJoiner(", ");
        // 获取请求头参数列表
        Map<String, Object> headerParamMap = new HashMap<>();
        HttpHeaders headers = request.getHeaders();
        for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
            headerParamMap.put(entry.getKey(), entry.getValue());
        }

        // 获取URL参数列表
        Map<String, Object> urlParamMap = new HashMap<>();
        MultiValueMap<String, String> queryParams = request.getQueryParams();
        for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
            List<String> fieldValueList = entry.getValue();
            String fieldValueStr = String.join(", ", fieldValueList);
            if (fieldValueList.size() > 1) {
                fieldValueStr = StringUtils.join("[", fieldValueStr, "]");
            }
            urlParamMap.put(entry.getKey(), fieldValueStr); // 说明，如果URL参数中某个key的value是数组，这里可能将无法还原出原始的url，如有需要，这部分编码仍要重构
        }
        StringBuffer requestUrl = new StringBuffer(request.getURI().toString());
        String urlParamStr = "";
        if (urlParamMap.size() > 0) {
            urlParamStr = "?" + urlParamMap.entrySet()
                    .stream()
                    .map((entry) -> StringUtils.join(entry.getKey(), "=", entry.getValue()))
                    .collect(Collectors.joining("&"));
            requestUrl.append(urlParamStr);
        }

        String remoteIp = StringUtils.EMPTY;
        InetSocketAddress remoteAddress = request.getRemoteAddress();
        if (remoteAddress != null) {
            remoteIp = StringUtils.join(remoteAddress.getAddress().getHostAddress(), ":", remoteAddress.getPort());
        }

        joiner.add(StringUtils.join("请求request_url=", requestUrl, " "));
        joiner.add(StringUtils.join("request_method=", request.getMethod()));
        joiner.add(StringUtils.join("请求remote_ip=", remoteIp));
        joiner.add(StringUtils.join("请求头 request_headers=", headerParamMap));
        joiner.add(StringUtils.join("地址入参 url_param=", urlParamStr));
        joiner.add(StringUtils.join("class_method=", packagePathName, ".", methodName));
        joiner.add(StringUtils.join("方法入参 method_args=", JSONUtil.toJsonStr(args)));
        return joiner;
    }

}
